<!doctype html>
<html>
    <head>
        <title>HT for Web 树组件手册</title>
        <meta charset="UTF-8">    
        <meta name="viewport" content="user-scalable=yes, width=1024">
        <style type="text/css"> 
            h1, h2, h3, h4, h5, h6, p, blockquote {
                margin: 0;
                padding: 0;
            }
            body {
                font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
                font-size: 13px;
                line-height: 18px;
                color: #737373;
                background-color: white; 
                margin: 10px 13px 10px 13px;
            }
            table {
                margin: 10px 0 15px 0;
                border-collapse: collapse;
            }
            td,th {	
                border: 1px solid #ddd;
                padding: 3px 10px;
            }
            th {
                padding: 5px 10px;	
            }
            a {
                color: #0069d6;
            }
            a:hover {
                color: #0050a3;
                text-decoration: none;
            }
            a img {
                border: none;
            }
            p {
                margin-bottom: 9px;
            }
            h1, h2, h3, h4, h5, h6 {
                color: #404040;
                line-height: 36px;
            }
            h1 {
                margin-bottom: 18px;
                font-size: 30px;
            }
            h2 {
                font-size: 24px;
            }
            h3 {
                font-size: 18px;
            }
            h4 {
                font-size: 16px;
            }
            h5 {
                font-size: 14px;
            }
            h6 {
                font-size: 13px;
            }
            hr {
                margin: 0 0 19px;
                border: 0;
                border-bottom: 1px solid #ccc;
            }
            blockquote {
                padding: 13px 13px 21px 15px;
                margin-bottom: 18px;
                font-family:georgia,serif;
                font-style: italic;
            }
            blockquote:before {
                content:"\201C";
                font-size:40px;
                margin-left:-10px;
                font-family:georgia,serif;
                color:#eee;
            }
            blockquote p {
                font-size: 14px;
                font-weight: 300;
                line-height: 18px;
                margin-bottom: 0;
                font-style: italic;
            }
            code, pre {
                font-family: Monaco, Andale Mono, Courier New, monospace;
            }
            code {
                background-color: #fee9cc;
                color: rgba(0, 0, 0, 0.75);
                padding: 1px 3px;
                font-size: 12px;
                -webkit-border-radius: 3px;
                -moz-border-radius: 3px;
                border-radius: 3px;
            }
            pre {
                display: block;
                padding: 14px;
                margin: 0 0 18px;
                line-height: 16px;
                font-size: 11px;
                border: 1px solid #d9d9d9;
                white-space: pre-wrap;
                word-wrap: break-word;
            }
            pre code {
                background-color: #fff;
                color:#737373;
                font-size: 11px;
                padding: 0;
            }
            sup {
                font-size: 0.83em;
                vertical-align: super;
                line-height: 0;
            }
            * {
                -webkit-print-color-adjust: exact;
            }
            @media screen and (min-width: 914px) {
                body {
                    width: 854px;
                    margin:10px auto;
                }
            }
            @media print {
                body,code,pre code,h1,h2,h3,h4,h5,h6 {
                    color: black;
                }
                table, pre {
                    page-break-inside: avoid;
                }
            }                        
            iframe{
                width: 100%;
                border: 1px solid #34495E;
                margin: 0;                
            }            
            .logo{
                vertical-align: middle;
            }

        </style>        
        <script>
            function init() {
                var logoSrc = '',
                    logos = document.querySelectorAll('.logo'),
                    i = 0;
                for (; i < logos.length; i++) {
                    logos[i].src = logoSrc;
                }
                
                var iframes = document.querySelectorAll('iframe'),
                    func = function(){};
                for (i=0; i < iframes.length; i++) {
                    var iframe = iframes[i];
                    
                    // a small hack to make it work on android
                    iframe.ontouchstart = func;
                    
                    var div = document.createElement('div');
                    div.innerHTML = '<a href="' + iframe.src + '" target="_blank">独立运行→</a>';
                    iframe.parentNode.insertBefore(div, iframe);
                }   
            }
        </script>    
    </head>
    <body onload="init();">
        <a href="http://www.hightopo.com"><img class="logo"></a>HT for Web 树组件手册
        <hr style="margin: 1px 0 20px 0">
<p>索引</p>

<ul><li><a href="#ref_overview">概述</a></li><li><a href="#ref_treeview">树组件</a></li></ul>

<hr/>

<div id="ref_overview"></div>

<h2>概述</h2>

<p><code>HT for Web</code>提供了树表组件类<code>ht.widget.TreeView</code>，用于显示<code>DataModel</code>数据容器中<code>Data</code>类型对象的父子关系树形结构，支持排序和过滤等功能。</p>

<p>通过<code>treeView = new ht.widget.TreeView(dataModel);</code>初始化构建一个树组件对象，<code>dataModel</code>参数为树组件绑定的数据模型，
该模型为空时树组件构造函数内部将创建一个新的数据模型进行绑定。</p>

<div id="ref_treeview"></div>

<h2>树组件</h2>

<p>树表组件类<code>ht.widget.TreeView</code>主要可配置属性和函数如下：</p>

<ul><li><code>enableToolTip()</code>和<code>disableToolTip()</code>开启和关闭文字提示</li><li><code>isDisabled()</code>和<code>setDisabled(true/false, iconURL)</code>可获取和设置整个组件处于不可用状态</li><li><code>addTopPainter(func)</code>和<code>removeTopPainter(func)</code>增加和删除顶层绘制器<code>function(g){...}</code></li><li><code>addBottomPainter(func)</code>和<code>removeBottomPainter(func)</code>增加和删除底层绘制器<code>function(g){...}</code></li><li><code>getRowHeight()</code>和<code>setRowHeight(20)</code>获取和设置行高</li><li><code>isRowLineVisible()</code>和<code>setRowLineVisible(true/false)</code>获取和设置行线是否可见，默认为<code>true</code></li><li><code>getRowLineColor()</code>和<code>setRowLineColor(color)</code>获取和设置行线颜色</li><li><code>getSortFunc()</code>和<code>setSortFunc(sortFunc)</code>获取和设置排序函数，决定层次中<code>children</code>的显示顺序</li><li><code>isChildrenSortable(parent)</code>判断是否对<code>parent</code>对象的孩子排序，默认返回<code>true</code>，可重载屏蔽孩子排序</li><li><code>getVisibleFunc()</code>和<code>setVisibleFunc()</code>获取和设置可见过滤器，其可过滤<code>DataModel</code>中的<code>Data</code>数据对象</li><li><code>getScrollBarColor()</code>和<code>setScrollBarColor(color)</code>获取和设置滚动条颜色</li><li><code>getScrollBarSize()</code>和<code>setScrollBarSize(6)</code>获取和设置滚动条宽度</li><li><code>isAutoHideScrollBar()</code>和<code>setAutoHideScrollBar(true/false)</code>获取和设置是否自动隐藏滚动条，默认为<code>true</code></li><li><code>getRootData()</code>和<code>setRootData(data)</code>指定树从哪个根节点进行展开，默认从<code>DataModel#getRoots()</code>的对象开始展示</li><li><code>isRootVisible()</code>和<code>setRootVisible(true/false)</code>确定<code>rootData</code>节点是否可见，默认为<code>true</code>，设置为<code>false</code>则隐藏根节点</li><li><code>getCheckMode()</code>和<code>setCheckMode(checkMode)</code>获取和设置当前组件<code>check</code>模式：<ul><li><code>null</code>：默认值，不启用<code>check</code>选择模式</li><li><code>default</code>：<code>check</code>模式的默认选择方式，即单击选中或取消选中，只影响当前点击中的<code>data</code>对象</li><li><code>children</code>：该<code>check</code>模式将同时影响点击中的<code>data</code>对象，以及其孩子对象</li><li><code>descendant</code>：该<code>check</code>模式将同时影响点击中的<code>data</code>对象，以及其所有子孙对象</li><li><code>all</code>：该<code>check</code>模式将同时影响点击中的<code>data</code>对象，以及其所有父辈和子孙对象</li></ul></li><li><code>getCheckIcon(data)</code>返回<code>data</code>对象对应的<code>check</code>图标，可重载自定义<code>check</code>图标，该函数在<code>checkMode</code>模式下有效</li><li><code>getFocusData()</code>、<code>setFocusData(data)</code>和<code>setFocusDataById(id)</code>在<code>checkMode</code>模式下图元除了被选中有<code>check</code>状态外，还可以有被点击行的<code>focus</code>状态</li><li><code>drawRow(g, data, selected, x, y, width, height)</code>绘制行内容，可重载自定义</li><li><code>drawRowBackground(g, data, selected, x, y, width, height)</code>绘制行背景色，默认仅在选中该行时填充选中背景色，可重载自定义</li><li><code>drawLabel(g, data, x, y, height)</code>绘制文本，可重载自定义，<code>label</code>一般绘制在最后因此没有<code>width</code>参数限制</li><li><code>drawIcon(g, data, x, y, width, height)</code>绘制图标，可重载自定义，这里<code>width</code>值取值于<code>getIconWidth</code>函数</li><li><code>getIconWidth(data)</code>返回<code>data</code>对象对应的图标宽度，默认如果有图标则以<code>indent</code>值为宽度，可重载自定义</li><li><code>getIndent()</code>和<code>setIndent(20)</code>获取和设置<code>indent</code>缩进，该参数一般用于指定图标的宽度</li><li><code>getDataAt(pointOrEvent)</code>传入逻辑坐标点或交互事件<code>event</code>参数，返回对应的<code>data</code>对象或空</li><li><code>getToolTip(event)</code>根据传入的交互事件，返回文本提示信息，可重载自定义</li><li><code>onDataDoubleClicked(data)</code>当<code>data</code>所在行被双击时回调，可重载对双击事件做响应          </li><li><code>onDataClicked(data)</code>当<code>data</code>所在行被单击时回调，可重载对单击事件做响应 </li><li><code>getLabel(data)</code>返回<code>data</code>对象显示的文字，默认返回<code>data.toLabel()</code>，可重载自定义</li><li><code>getIcon(data)</code>返回<code>data</code>对象对应的<code>icon</code>图标，可重载自定义                    </li><li><code>getLabelFont(data)</code>返回<code>data</code>对应的文本字体，可重载自定义</li><li><code>getLabelColor(data)</code>返回<code>data</code>对应的文本颜色，可重载自定义</li><li><code>getSelectBackground(data)</code>和<code>setSelectBackground(color)</code>获取和设置行选中背景颜色</li><li><code>getStartRowIndex()</code>返回当前可见区域的起始行索引</li><li><code>getEndRowIndex()</code>返回当前可见区域的结束行索引</li><li><code>getRowDatas()</code>返回当前显示的<code>Data</code>对象数组，该数组已被排序和过滤</li><li><code>getRowIndex(data)</code>返回<code>data</code>对象所在的行索引</li><li><code>getRowSize()</code>返回当前可见行总行数</li><li><code>isVisible(data)</code>判断<code>data</code>对象是否可见，可重载自定义</li><li><code>getDataModel()</code>和<code>setDataModel(dataModel)</code>获取和设置绑定的<code>DatModel</code>数据模型</li><li><code>makeVisible(data)</code>该函数触发组件滚动到确保<code>data</code>对象出现在可见区域。</li><li><code>invalidateModel()</code>该函数触发组件重新排序过滤加载数据，一般组件会自动调用，除非数据变化但未派发事件时才需强制调用</li><li><code>redraw()</code>重绘刷新，注意该函数不会触发数据模型的重新加载</li><li><code>invalidateData(data)</code>调用该函数会重绘<code>data</code>对象所在行</li><li><code>getLevel(data)</code>获取当前<code>data</code>的缩减层次，一般结合<code>indent</code>参数用于绘制</li><li><code>getExpandIcon()</code>和<code>setExpandIcon(icon)</code>获取和设置<code>toggle</code>的展开图标</li><li><code>getCollapseIcon()</code>和<code>setCollapseIcon(icon)</code>获取和设置<code>toggle</code>的关闭图标</li><li><code>getToggleIcon(data)</code>返回当前<code>data</code>对象对应的展开或合并图标，可重载自定义</li><li><code>isExpanded(data)</code>判断<code>data</code>对象是否展开</li><li><code>expand(data)</code>展开<code>data</code>对象</li><li><code>onExpanded(data)</code>展开<code>data</code>对象时调用，可重载做后续处理</li><li><code>collapse(data)</code>合并<code>data</code>对象</li><li><code>onCollapsed(data)</code>合并<code>data</code>对象时调用，可重载做后续处理</li><li><code>expandAll()</code>展开所有对象 </li><li><code>collapseAll()</code>合并所有对象</li><li><code>checkData(data)</code>勾选<code>data</code>对象，该函数将根据当前<code>checkMode</code>类型做相应选择处理</li><li><code>handleDragAndDrop(event, state)</code>该函数默认为空，若该函数被重载，则<code>pan</code>平移组件功能将被关闭<ul><li><code>event</code>鼠标或<code>Touch</code>交互事件</li><li><code>state</code>当前状态，先后会有<code>prepare</code>-<code>begin</code>-<code>between</code>-<code>end</code>四种过程</li></ul></li></ul>

<p><iframe src="examples/example_checkmode.html" style="height:500px"></iframe></p>

<p>以下代码设置了展开和关闭的<code>toggle</code>图标，重载<code>treeView.getIcon</code>函数实现节点展开和合并是显示不同的图标效果</p>

<pre><code>treeView.setExpandIcon(&#39;images/expand.gif&#39;);
treeView.setCollapseIcon(&#39;images/collapse.gif&#39;);
treeView.getIcon = function (data) {
    if(data.a(&#39;class&#39;)){
        return &#39;images/class.png&#39;;
    }else{
        if (this.isExpanded(data)) {
            return &#39;images/dir-open.gif&#39;;
        } else {
            return &#39;images/dir.gif&#39;;
        }                        
    }
};</code></pre>

<p>以下代码通过<code>treeView.setSortFunc</code>设置了排序函数，实现将<code>package</code>出现在<code>class</code>类型之前，同类型的实现按文字顺序排序</p>

<pre><code>treeView.setSortFunc(function(d1, d2){
    if(d1.a(&#39;class&#39;) &amp;&amp; !d2.a(&#39;class&#39;)){
        return 1;
    }
    if(!d1.a(&#39;class&#39;) &amp;&amp; d2.a(&#39;class&#39;)){
        return -1;
    }
    return d1.getName().localeCompare(d2.getName());
}); </code></pre>

<p><code>checkData</code>函数选中图元，并且更加当前<code>checkMode</code>影响相应的相关图元选中；
<code>setFocusData</code>将使得图元在<code>checkMode</code>模式下依然具备行选中的<code>focus</code>效果；
<code>makeVisible</code>将使得<code>treeView</code>组件展开并滚动到指定<code>data</code>图元可见的效果。</p>

<pre><code>var data = dataModel.getDataByTag(&#39;ht.widget.TreeView&#39;);
treeView.checkData(data);
treeView.setFocusData(data);
treeView.makeVisible(data); </code></pre>

<p><iframe src="examples/example_draganddrop.html" style="height:400px"></iframe></p>

<p>该例子重载了<code>treeView.handleDragAndDrop</code>函数，在<code>prepare</code>阶段通过<code>treeView.sm().ss(data);</code>设置了点击所在图元的选中，
<code>begin</code>阶段将一个矩形颜色背景的<code>div</code>组件添加到<code>document.body</code>，在<code>between</code>阶段移动<code>div</code>组件，
最终在<code>end</code>阶段创建相应的<code>Node</code>图元到<code>GraphView</code>组件，并删除<code>document.body</code>的<code>div</code>组件完成整该拖拽过程。</p>

<pre><code>treeView.handleDragAndDrop = function(e, state){
    var data;
    if(state === &#39;prepare&#39;){
        data = treeView.getDataAt(e);
        treeView.sm().ss(data);
        if(data &amp;&amp; data.getIcon() === &#39;color&#39;){
            if(!currentDiv){
                currentDiv = ht.Default.createElement(&#39;div&#39;);
                currentDiv.style.width = size + &#39;px&#39;;
                currentDiv.style.height = size + &#39;px&#39;;
            }
            currentDiv.style.background = data.getName();                                
        }
    }
    else if(state === &#39;begin&#39;){
        if(currentDiv){
            var pagePoint = ht.Default.getPagePoint(e);
            currentDiv.style.left = pagePoint.x - size/2 + &#39;px&#39;;
            currentDiv.style.top = pagePoint.y - size/2 + &#39;px&#39;;
            document.body.appendChild(currentDiv);
        }
    }
    else if(state === &#39;between&#39;){
        if(currentDiv){
            var pagePoint = ht.Default.getPagePoint(e);
            currentDiv.style.left = pagePoint.x - size/2 + &#39;px&#39;;
            currentDiv.style.top = pagePoint.y - size/2 + &#39;px&#39;;
        }
    }
    else{
        if(currentDiv){                            
            if(ht.Default.containedInView(e, graphView)){     
                var node = new ht.Node();
                node.setSize(30, 30);
                node.setPosition(graphView.lp(e));
                node.s({
                    &#39;select.type&#39;: &#39;circle&#39;,
                    &#39;shape&#39;: &#39;circle&#39;,
                    &#39;shape.background&#39;: currentDiv.style.background,
                    &#39;shape.gradient&#39;: &#39;radial.center&#39;
                });
                graphView.dm().add(node);
            }
            document.body.removeChild(currentDiv);
            currentDiv = null;                            
        }
    }
};</code></pre>

<p>该例子通过<code>graphView.getView().style.background = &#39;#FCFCFC&#39;;</code>设置了背景色，
通过<code>graphView.addBottomPainter</code>在底部绘制了一段文字提示说明：</p>

<pre><code>graphView.getView().style.background = &#39;#FCFCFC&#39;;
graphView.addBottomPainter(function(g){
    ht.Default.drawText(g, &#39;Drag tree node to drop here ..&#39;, &#39;24px Arial&#39;, &#39;lightgray&#39;, 50, 100, 0, 0, &#39;left&#39;);
});</code></pre>    <hr id="contact" style="margin: 20px 0 1px 0">
    <a href="http://www.hightopo.com"><img class="logo"></a>欢迎交流 <a href="mailto:service@hightopo.com">service@hightopo.com</a>
</body>
</html>
